package com.woate.wingframework.test.spring.listener;

import com.woate.wingframework.annotations.devtime.CreateTable;
import com.woate.wingframework.annotations.devtime.StoreData;
import com.woate.wingframework.lang.FastDate;
import com.woate.wingframework.test.persistence.metadata.ColumnMetadata;
import com.woate.wingframework.test.persistence.metadata.TableMetadata;
import com.woate.wingframework.test.persistence.utils.EntityUtils;
import com.woate.wingframework.test.persistence.utils.PersistenceUtils;
import com.woate.wingframework.utils.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;

import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

public class PersistenceTestExecutionListener extends AbstractTestExecutionListener {
    private static final Log logger = LogFactory.getLog(PersistenceTestExecutionListener.class);
    Class[] entities = null;

    @Override
    public void beforeTestMethod(TestContext ctx) throws Exception {
        final Method testMethod = ctx.getTestMethod();
        final Class<?> testClass = ctx.getTestClass();
        CreateTable createTable = testMethod.getAnnotation(CreateTable.class);
        if(createTable != null){
            Class[] clazzs = createTable.value();
            entities = clazzs;
            boolean test = createTable.test();
            boolean drop = createTable.drop();
            for (Class clazz : clazzs){
                JdbcTemplate jdbcTemplate = (JdbcTemplate)ctx.getApplicationContext().getBean("jdbcTemplate");
                if(drop){
                    String dropSql = PersistenceUtils.dropTable(clazz, test);
                    logger.info("this is a auto drop table sql:\n" + dropSql);
                    jdbcTemplate.execute(dropSql);
                }
                String createSql = PersistenceUtils.createTable(clazz, test);
                logger.info("this is a auto create table sql:\n" + createSql);
                jdbcTemplate.execute(createSql);
            }
        }
        super.beforeTestMethod(ctx);
    }

    @Override
    public void afterTestMethod(TestContext ctx) throws Exception {
        final Method testMethod = ctx.getTestMethod();
        final Class<?> testClass = ctx.getTestClass();
        StoreData storeData = testMethod.getAnnotation(StoreData.class);
        //遍历创建的实体对应的表
        for (Class clazz : entities){
            //获取表
            TableMetadata tableMetadata = EntityUtils.extractTable(clazz);
            final Map<String, ColumnMetadata> columns = EntityUtils.extractFields(clazz);
            StringBuilder sql = new StringBuilder("SELECT ");
            for (String col : columns.keySet()){
                sql.append(col).append(",");
            }
            sql.deleteCharAt(sql.length() -1);
            sql.append(" ").append(tableMetadata.getName());
            JdbcTemplate jdbcTemplate = (JdbcTemplate)ctx.getApplicationContext().getBean("jdbcTemplate");
            List<String> list = jdbcTemplate.query(sql.toString(), new RowMapper<String>() {
                @Override
                public String mapRow(ResultSet resultSet, int i) throws SQLException {
                    String message = "";
                    for (int k = 0; k < columns.size() ; k++){
                        message += resultSet.getString(k);
                    }
                    return message;
                }
            });
            File dir =  new File(StringUtils.dotToSlash(testClass.getName()));
            if(!dir.exists()){
                dir.mkdirs();
            }
            FileWriter writer = new FileWriter(new File(dir, testMethod.getName() + new FastDate().toString()));
            for (String line : list){
                writer.write(line);
            }
            writer.close();
        }
        super.afterTestMethod(ctx);
    }
}
